#[test]  // lrc歌词调整
#[ignore]
fn test027() {
    use std::io::{Write, Read};
    use std::fs::File;
    use encoding::{Encoding, EncoderTrap, all::GB18030};
    use regex::Regex;

    fn offset_lrc(file_path: &str, offset: i32) {
        let mut output = File::create("out.txt").unwrap();
        let re = Regex::new(r"^\[(\d{2}):(\d{2})\.(\d{2})](.*)").unwrap();

        let mut file = File::open(file_path).unwrap();
        let mut contents = String::new();
        file.read_to_string(&mut contents).unwrap();

        for line in contents.lines() {
            if !re.is_match(line) {
                continue;
            }

            let cap = re.captures(line).unwrap();
            let a: i32 = cap[1].parse().unwrap();
            let b: i32 = cap[2].parse().unwrap();
            let c: i32 = cap[3].parse().unwrap();
            let d = &cap[4];

            // offset单位0.01s
            let mut t = a * 60 * 100 + b * 100 + c + offset;
            let c = t % 100;
            t = (t - c) / 100;
            let b = t % 60;
            t = (t - b) / 60;
            let a = t;

            let out_line = GB18030.encode(format!("[{:02}:{:02}.{:02}]{}\n", a, b, c, d).as_str(),
                                          EncoderTrap::Strict).unwrap();
            output.write_all(&out_line).unwrap();
        }
    }

    offset_lrc(r"C:\Users\zhang\Videos\珊瑚颂\珊瑚颂-utf8.lrc", 100);
}

#[test]  // 链表1
#[ignore]
fn test014() {
    use std::mem;

    struct List {
        head: Link,
    }

    enum Link {
        Empty,
        More(Box<Node>),
    }

    struct Node {
        elem: i32,
        next: Link,
    }

    impl List {
        fn new() -> Self {
            List { head: Link::Empty }
        }

        fn push(&mut self, val: i32) {
            let new_node = Box::new(Node { elem: val, next: mem::replace(&mut self.head, Link::Empty) });
            self.head = Link::More(new_node);
        }

        fn pop(&mut self) -> Option<i32> {
            match mem::replace(&mut self.head, Link::Empty) {
                Link::Empty => None,
                Link::More(node) => {
                    self.head = node.next;
                    Some(node.elem)
                }
            }
        }
    }

    impl Drop for List {
        fn drop(&mut self) {
            let mut cur_link = mem::replace(&mut self.head, Link::Empty);
            while let Link::More(mut boxed_node) = cur_link {
                cur_link = mem::replace(&mut boxed_node.next, Link::Empty);
            }
        }
    }

    let mut list = List::new();
    assert_eq!(list.pop(), None);

    list.push(1);
    list.push(2);
    list.push(3);

    assert_eq!(list.pop(), Some(3));
    assert_eq!(list.pop(), Some(2));
    assert_eq!(list.pop(), Some(1));
    assert_eq!(list.pop(), None);
    assert_eq!(list.pop(), None);
}

#[test]  // fft use complex
#[ignore]
fn test005() {
    use std::fmt;
    use std::ops::{Add, Sub, Mul};
    use std::f64;

    #[derive(Copy, Clone)]
    struct Complex {
        real: f64,
        imag: f64,
    }

    impl fmt::Display for Complex {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if self.imag >= 0.0_f64 {
                write!(f, "({}+{}i)", self.real, self.imag)
            } else {
                write!(f, "({}-{}i)", self.real, -self.imag)
            }
        }
    }

    impl Add for Complex {
        type Output = Complex;
        fn add(self, other: Complex) -> Complex {
            Complex { real: self.real + other.real, imag: self.imag + other.imag }
        }
    }

    impl Sub for Complex {
        type Output = Complex;
        fn sub(self, other: Complex) -> Complex {
            Complex { real: self.real - other.real, imag: self.imag - other.imag }
        }
    }

    impl Mul for Complex {
        type Output = Complex;
        fn mul(self, other: Complex) -> Complex {
            Complex {
                real: self.real * other.real - self.imag * other.imag,
                imag: self.real * other.imag + self.imag * other.real,
            }
        }
    }

    impl Complex {
        fn new(a: f64, b: f64) -> Complex {
            Complex { real: a, imag: b }
        }
    }


    fn bit_rev(data: &mut Vec<Complex>) {
        let mut j = 0_usize;
        let mut m;
        let n = data.len();
        for i in 0..n {
            if j > i {
                let tmp = data[i];
                data[i] = data[j];
                data[j] = tmp;
            }

            m = n / 2;
            while j >= m && m != 0 {
                j -= m;
                m >>= 1;
            }
            j += m;
        }
    }

    fn fft(data: &mut Vec<Complex>) {
        let n = data.len();
        let mm = {
            let mut m = 0;
            let mut i = n;
            while i > 1 {
                i = i >> 1;
                m += 1;
            }
            m
        };

        bit_rev(data);

        for m in 0..mm {
            let kk = n >> (m + 1);

            for k in 0..kk {
                let jj = 2 << m;
                let base = k * jj;

                for j in 0..jj / 2 {
                    let t = base + j;
                    let w = Complex::new(
                        (-2.0 * f64::consts::PI * j as f64 * kk as f64 / n as f64).cos(),
                        (-2.0 * f64::consts::PI * j as f64 * kk as f64 / n as f64).sin(),
                    );
                    let wn = data[t + jj / 2] * w;
                    let tmp = data[t];
                    data[t] = data[t] + wn;
                    data[t + jj / 2] = tmp - wn;
                }
            }
        }
    }

    fn show(data: &mut Vec<Complex>) {
        for (i, e) in data.iter().enumerate() {
            println!("{}.{}", i, e);
        }
    }

    let n = 128;
    let mut data = Vec::with_capacity(n as usize);
    for i in 0..n {
        data.push(Complex::new(i as f64, 0.0));
    }

    fft(&mut data);
    show(&mut data);
}

#[test]  // path
#[ignore]
fn test004() {
    use std::path::Path;

    let path = Path::new(".");
    let _display = path.display();
    let new_path = path.join("a").join("b").join("c/d");
    match new_path.to_str() {
        Some(s) => println!("path is {}", s),
        None => panic!("invalid path"),
    }
}

#[test]  // thread
#[ignore]
fn test003() {
    use std::thread;
    let data = "86967897737416471853297327050364959
        11861322575564723963297542624962850
        70856234701860851907960690014725639
        38397966707106094172783238747669219
        52380795257888236525459303330302837
        58495327135744041048897885734297812
        69920216438980873548808413720956532
        16278424637452589860345374828574668";
    let chunked_data = data.split_ascii_whitespace();
    let mut children = vec![];
    for (i, d) in chunked_data.enumerate() {
        children.push(thread::spawn(move || -> u32 {
            let result = d
                .chars()
                .map(|c| c.to_digit(10).expect("should be a digit"))
                .sum();
            println!("processed {}.{}, result={}", i, d, result);
            result
        }));
    }

    let mut result_list = vec![];
    for i in children {
        result_list.push(i.join().unwrap());
    }
    println!("{:?}", result_list);
}

#[test]  // thread
#[ignore]
fn test002() {
    use std::thread;
    static MAX_THREADS: i32 = 10;

    let mut children = vec![];
    for i in 0..MAX_THREADS {
        children.push(thread::spawn(move || {
            println!("this is thread number {}", i);
        }));
    }

    // wait for finish
    for child in children {
        let _ = child.join();
    }
}

#[test]  // link list
//#[ignore]
fn test001() {
    type Link = Option<Box<ListNode>>;

    #[derive(PartialEq, Eq, Clone, Debug)]
    pub struct ListNode {
        pub value: i32,
        pub next: Link,
    }

    struct List { head: Link };

    impl List {
        fn new() -> Self {
            List { head: None }
        }

        fn push(&mut self, val: i32) {
            let new_node = Box::new(ListNode { value: val, next: self.head.take() });
            self.head = Some(new_node);
        }

        fn pop(&mut self) -> Option<i32> {
            self.head.take().map(|x| {
                self.head = x.next;
                x.value
            })
        }

        fn show(&self) {
            let mut p = self.head.clone();
            while let Some(x) = p {
                print!("[{}]", x.value);
                p = x.next;
            }
            println!();
        }
    }

    let mut list = List::new();
    list.push(1);
    list.push(2);
    list.push(3);
    list.show();
    list.pop();
    list.show();
}

fn main() {
    println!("hello, world!");
}

